﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;

namespace Mines.Ajax
{
    class AjaxHandlerFactory : IHttpHandlerFactory
    {
        public void ReleaseHandler(IHttpHandler handler)
        {
        }

        public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
        {
            var alias = System.IO.Path.GetFileName(context.Request.Path);

            alias = alias.Substring(0, alias.IndexOf('.'));

            var ajaxModel = Common.ajaxModels.Where((m) => m.Alias == alias).FirstOrDefault();

            Exception ex;
            if (ajaxModel==null)
            {
                ex = new AjaxTypeNullException();
            }


            if (requestType == "POST")
            {
                var methodName = context.Request.Headers["method"];

                if (!string.IsNullOrEmpty(methodName))
                {
                    byte[] byts = new byte[context.Request.InputStream.Length];
                    context.Request.InputStream.Read(byts, 0, byts.Length);
                    string req = System.Text.Encoding.Default.GetString(byts);

                    var args = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(req);
                    
                    var d = string.Empty;
                    foreach (var k in args.Keys)
                    {
                        d += k + ",";
                    }
                    d = d.Trim(',');


                    var method = ajaxModel.Methods.Where((m) => m.Name == methodName && m.ParamNames == d).SingleOrDefault();

                    if (method==null)
                    {
                        ex = new AjaxArgumentsException();
                        throw ex;
                    }

                    var ptypes = new List<object>();

                    try
                    {
                        object arg = null;
                        for (var i = 0; i < method.Parameters.Length; i++)
                        {
                            arg = args[method.Parameters[i].Name];
                            if (arg == null || string.IsNullOrEmpty(arg.ToString()) || arg.ToString().ToLower() == "null")
                                ptypes.Add(null);
                            else
                            {
                                if (method.Parameters[i].ParameterType == arg.GetType())
                                    ptypes.Add(arg);
                                else
                                {
                                    var pi = Newtonsoft.Json.JsonConvert.DeserializeObject(Newtonsoft.Json.JsonConvert.SerializeObject(arg), method.Parameters[i].ParameterType);
                                    ptypes.Add(pi);
                                }
                            }
                        }

                    }
                    catch (Exception ex1)
                    {
                        throw ex1;
                    }
                    switch (method.SessionState)
                    {
                        case SessionState.ReadOnly:
                            return new AjaxReadOnlySessionHandler(ajaxModel.Type, method, ptypes.ToArray());
                        case SessionState.ReadAndWrite:
                            return new AjaxRequiresSessionHandler(ajaxModel.Type, method, ptypes.ToArray());
                        default:
                            return new AjaxNoneSessionHandler(ajaxModel.Type, method, ptypes.ToArray());
                    }
                }
                else
                {
                    return new InitHttpHandler(ajaxModel);
                }
            }
            else
            {
                return new InitHttpHandler(ajaxModel);
            }
        }
    }
}